﻿namespace C11_Ex02_1
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class CardsTable
    {
        private Cell[,] m_Board;
        private int m_BoardWidth;
        private int m_BoardHeight;
        private Random RandomNumberGenerator = new Random();

        public int BoardWidth
        {
            get { return m_BoardWidth; }
        }
        
        public int BoardHeight
        {
            get { return m_BoardHeight; }
        }

        public CardsTable(int i_BoardWidth, int i_BoardHeight)
        {
            m_BoardWidth = i_BoardWidth;
            m_BoardHeight = i_BoardHeight;
            allocateBoardMemory();
            randomlyFillCellWithValues();
        }

        private void allocateBoardMemory()
        {
            m_Board = new Cell[m_BoardHeight, m_BoardWidth];

            for(int CurrentRow = 0 ; CurrentRow < m_BoardHeight; CurrentRow++)
            {
                for(int CurrentColumn = 0 ; CurrentColumn < m_BoardWidth; CurrentColumn++)
                {
                    m_Board[CurrentRow, CurrentColumn] = new Cell(new BoardPosition(CurrentRow, CurrentColumn));
                }
            }
        }

        private void randomlyFillCellWithValues()
        {
            Char ValueToInsert = 'A';
            Cell[] EmptyCells= null;

            do
            {
                EmptyCells = createEmptyCellsArray();
                chooseRandomCellFromEmptyCellsAndInsertValue(EmptyCells, ValueToInsert.ToString());
                EmptyCells = createEmptyCellsArray();
                chooseRandomCellFromEmptyCellsAndInsertValue(EmptyCells, ValueToInsert.ToString());
                ValueToInsert++;
            } while (EmptyCells.Length > 1);
        }

        private void chooseRandomCellFromEmptyCellsAndInsertValue(Cell[] io_EmptyCells, String i_Value)
        {
            int RandomCellNumber;

            io_EmptyCells = createEmptyCellsArray();
            RandomCellNumber = RandomNumberGenerator.Next(0, io_EmptyCells.Length);
            io_EmptyCells[RandomCellNumber].CellValue = i_Value;
        }

        private Cell[] createEmptyCellsArray()
        {
            List<Cell> EmptyCellsList = new List<Cell>();

            foreach(Cell CellsOnBoard in m_Board)
            {
                if (!CellsOnBoard.HaveValue())
                {
                    EmptyCellsList.Add(CellsOnBoard);
                }
            }

            return EmptyCellsList.ToArray();
        }

        public BoardPosition[] CreateHiddenCellsArray()
        {
            List<BoardPosition> HiddenCellsList = new List<BoardPosition>();
            
            for(int CurrentRow = 0 ; CurrentRow < m_BoardHeight; CurrentRow++)
            {
                for (int CurrentColumn = 0; CurrentColumn < m_BoardWidth; CurrentColumn++)
                {
                    if (!m_Board[CurrentRow, CurrentColumn].IsCellRevealed())
                    {
                        HiddenCellsList.Add(new BoardPosition(CurrentRow, CurrentColumn));
                    }
                }
            }

            return HiddenCellsList.ToArray();
        }

        public bool IsCoordinateInBoardRange(BoardPosition i_Position)
        {
            bool ReturnValue = true;

            if((i_Position.Column < 0) || (i_Position.Column >= m_BoardWidth) || (i_Position.Row < 0) || (i_Position.Row >= m_BoardHeight))
            {
                ReturnValue = false;
            }

            return ReturnValue;
        }

        public bool IsCellRevealed(BoardPosition i_Position)
        {
            return m_Board[i_Position.Row, i_Position.Column].IsCellRevealed();
        }

        public String GetCellValue(BoardPosition i_Position)
        {
            return m_Board[i_Position.Row, i_Position.Column].CellValue;
        }

        public bool CompareCellsValues(BoardPosition i_Position1, BoardPosition i_Position2)
        {
            return m_Board[i_Position1.Row, i_Position1.Column].CompareCellValue(m_Board[i_Position2.Row, i_Position2.Column]);
        }

        public void OpenCell(BoardPosition i_Position)
        {
            m_Board[i_Position.Row, i_Position.Column].FlipCardInCell();
        }

        public void CloseCell(BoardPosition i_Position)
        {
            m_Board[i_Position.Row, i_Position.Column].FlipCardInCell();
        }

        public bool AreThereAnyHiddenCards()
        {
            bool ReturnValue = false;
            
            for (int CurrentRow = 0; (CurrentRow < m_BoardHeight) && (!ReturnValue) ; CurrentRow++)
            {
                for (int CurrentColumn = 0; CurrentColumn < m_BoardWidth; CurrentColumn++)
                {
                    if (!m_Board[CurrentRow, CurrentColumn].IsCellRevealed())
                    {
                        ReturnValue = true;
                        break;
                    }
                }
            }

            return ReturnValue;
        }
    }
}

